//
// Created by guo on 24-8-30.
//

#include "BBServer.h"
#include <boost/static_string.hpp>

bool BBServer::init(const std::string &ip, uint16_t port) {
    if(!_server){
        _server = new TCPServer(ip,port);
        return true;
    }else{
        return false;
    }
}

void BBServer::run() {
    std::thread handle_thread(&BBServer::handle_data,this);

    _server->run(1);
    handle_thread.join();
}

void BBServer::handle_data() {
    QueueDataPtr queue_data;
    std::vector<std::pair<BBMsg,std::string>> msgs;
    while(1){
        bool ret = _server->get_data(queue_data);
        if(ret){
            parse_data(queue_data->data,msgs);
            handle_msg(queue_data->session_name,msgs);
        }else{
            std::this_thread::sleep_for(std::chrono::milliseconds(80));
        }
    }
}

void BBServer::parse_data(const std::string &data, std::vector<std::pair<BBMsg,std::string> > &vec_msg) {
    vec_msg.clear();
    if(data.size() < sizeof(BBMsg)){
        return;
    }

    std::string header;
    header.resize(2);
    header[0] = 0xEF;
    header[1] = 0x06;

    size_t pos = 0;
    size_t header_pos = 0;
    header_pos = data.find(header,pos);
    if(header_pos == std::string::npos){
        return;
    }
    std::string msg_data = data.substr(header_pos,sizeof(BBMsg));
    BBMsg* msg = (BBMsg*)msg_data.data();
    auto pair = std::make_pair(*msg,std::string(data.data()+header_pos+sizeof(BBMsg),msg->len));
    vec_msg.push_back(pair);
}

void BBServer::handle_msg(const std::string& session_name, std::vector<std::pair<BBMsg,std::string>> &vec_msg) {
    for(const auto& bbmsg_pair : vec_msg){
        switch (static_cast<BBMsgType>(bbmsg_pair.first.type)) {
            case BBMsgType::SET:{
                std::string key_str(reinterpret_cast<const char *>(bbmsg_pair.first.key),
                                    strlen(reinterpret_cast<const char *>(bbmsg_pair.first.key)));
                _shared_locker.lock();
                if(_bb_map.find(key_str) == _bb_map.end()){
                    _bb_map.insert(std::make_pair(key_str, bbmsg_pair.second));
                }else{
                    _bb_map[key_str] = bbmsg_pair.second;
                }
                _shared_locker.unlock();
                break;
            }
            case BBMsgType::GET:{
                std::string key_str(reinterpret_cast<const char *>(bbmsg_pair.first.key),
                                    strlen(reinterpret_cast<const char *>(bbmsg_pair.first.key)));
                _shared_locker.lock_shared();
                if(_bb_map.find(key_str) == _bb_map.end()){
                    std::string raw_data;
                    BBMsg::gen_raw_data(BBMsgType::GET,BBMsgError::NO_VALUE,key_str,raw_data);
                    _server->send(session_name,raw_data);
                }else{
                    std::string& value = _bb_map[key_str];
                    std::string raw_data;
                    BBMsg::gen_raw_data(BBMsgType::GET, BBMsgError::NO_ERROR, key_str, raw_data, value);
                    _server->send(session_name, raw_data);
                }
                _shared_locker.unlock_shared();
                break;
            }
            case BBMsgType::ERASE:{
                std::string key_str(reinterpret_cast<const char *>(bbmsg_pair.first.key),
                                    strlen(reinterpret_cast<const char *>(bbmsg_pair.first.key)));
                _shared_locker.lock();
                _bb_map.erase(key_str);
                _shared_locker.unlock();
                break;
            }
            case BBMsgType::UNKNOWN:
                break;
        }
    }
}
